﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Web.Script.Serialization;
using Ext.Net;
using Ext.Net.Utilities;
using Newtonsoft.Json.Linq;


namespace KamLib
{
    [Serializable]
    public class UiKey : ISerializable
    {
        public UiKey() { }
        public UiKey(string json)
        {
            FromJson(json);
        }
        public UiKey(UiLogicNode logic)
        {
            LID = logic.Controller.LID;
            LIID = logic.LIID;
            CID = logic.ControlID;
        }

        public string LID;
        public string LIID;
        public string CID;
        public bool IsAdding;
        public Dictionary<string, object> ID { get; set; }
        public Dictionary<string, object> MasterID { get; set; }
        public UiKey MasterKey { get; set; }
        public bool IsNew { get { return ID == null || ID.Count == 0; } }
        public UiKey[] DetailKeys { get; set; }

        public static implicit operator UiKey(string json)
        {
            return new UiKey(json);
        }

        public object this[string name]
        {
            get { return ID == null ? null : ID[name]; }
            set
            {
                if (ID == null)
                    ID = new Dictionary<string, object>();
                ID[name] = value;
            }
        }

        public object SimpleID { get { return ID != null && ID.Count == 1 ? ID.First().Value : null; } }

        public string ToJson(bool full = true)
        {
            var sb = new StringBuilder();
            sb.Append("{lid:'" + LID + "',liid:'" + LIID + "'");
            if (CID.IsNotEmpty())
                sb.Append(",cid:'" + CID + "'");
            if (IsAdding)
                sb.Append(",isnew:1");
            if (ID != null && ID.Count > 0)
                sb.Append(",id:" + JSON.Serialize(ID));
            if (MasterID != null && MasterID.Count > 0)
                sb.Append(",mid:" + JSON.Serialize(MasterID));
            if (full)
            {
                if (MasterKey != null)
                    sb.Append(",mkey:" + MasterKey.ToJson());
                if (DetailKeys != null)
                    sb.Append(",details:[" + DetailKeys.Select(a => a.ToJson(false)).Join(",") + "]");
            }
            sb.Append('}');
            return sb.ToString();
        }

        public void ToJson(IDictionary<string, object> d, bool full = true)
        {
            if (LID.IsNotEmpty())
                d["lid"] = LID;
            if (LIID.IsNotEmpty())
                d["liid"] = LIID;
            if (IsAdding)
                d["isnew"] = 1;
            if (CID.IsNotEmpty())
                d["cid"] = CID;
            if (ID != null && ID.Count > 0)
                d["id"] = ID;
            if (MasterID != null && MasterID.Count > 0)
                d["mid"] = MasterID;
            if (full)
            {
                if (MasterKey != null)
                    d["mkey"] = MasterKey;
                if (DetailKeys != null)
                    d["mkey"] = DetailKeys;
            }
        }

        public UiKey FromJson(IDictionary<string, object> d)
        {
            LID = (string)d.Try("lid");
            LIID = (string)d.Try("liid");
            CID = (string)d.Try("cid");
            IsAdding = d.Try("isnew") != null;
            ID = ((JObject)d.Try("id")).ToDictionary();
            MasterID = ((JObject)d.Try("mid")).ToDictionary();
            var dmkey = ((JObject)d.Try("mkey")).ToDictionary();
            if (dmkey != null)
                MasterKey = new UiKey().FromJson(dmkey);
            var dkey = (JArray)d.Try("details");
            if (dkey != null)
                DetailKeys = dkey.Select(a => new UiKey().FromJson(((JObject)a).ToDictionary())).ToArray();

            return this;
        }

        public UiKey FromJson(string json)
        {
            return json.IsEmpty() ? this : FromJson(JSON.Deserialize<Dictionary<string, object>>(json));
        }

        public override string ToString()
        {
            return ToJson();
        }

        protected UiKey(SerializationInfo info, StreamingContext context)
        {
            try { LID = info.GetString("lid"); }
            catch (SerializationException) { }
            try { LIID = info.GetString("liid"); }
            catch (SerializationException) { }
            try { CID = info.GetString("cid"); }
            catch (SerializationException) { }
            try { IsAdding = info.GetBoolean("isnew"); }
            catch (SerializationException) { }
            try { ID = (Dictionary<string, object>)info.GetValue("id", typeof(Dictionary<string, object>)); }
            catch (SerializationException) { }
            try { MasterID = (Dictionary<string, object>)info.GetValue("mid", typeof(Dictionary<string, object>)); }
            catch (SerializationException) { }
            try { MasterKey = (UiKey)info.GetValue("mkey", typeof(UiKey)); }
            catch (SerializationException) { }
        }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (LID.IsNotEmpty()) info.AddValue("lid", LID);
            if (LIID.IsNotEmpty()) info.AddValue("liid", LIID);
            if (CID.IsNotEmpty()) info.AddValue("cid", CID);
            if (IsAdding) info.AddValue("isnew", 1);
            if (ID != null) info.AddValue("id", ID);
            if (MasterID != null) info.AddValue("mid", MasterID);
            if (MasterKey != null) info.AddValue("mkey", MasterKey);
        }
    }

    //public class BiKeyConverter : JavaScriptConverter
    //{
    //    private readonly ReadOnlyCollection<Type> _supportedTypes = new ReadOnlyCollection<Type>(new[] { typeof(BiKey) });
    //    public override IEnumerable<Type> SupportedTypes { get { return _supportedTypes; } }

    //    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    //    {
    //        return new BiKey().FromJson(dictionary);
    //    }

    //    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    //    {
    //        var d = new Dictionary<string, object>();
    //        ((BiKey)obj).ToJson(d);
    //        return d;
    //    }
    //}
}